#include "Direct3DResource.h"

#pragma comment(lib, "d3d11")

using namespace DirectXCore;

//#define ENABLE_D3D11_CREATE_DEVICE_DEBUG

void Direct3DResource::Initialize() {
	HRESULT hResult = S_OK;
	D3D_FEATURE_LEVEL featureLevelSupported;
	D3D_FEATURE_LEVEL featureLevels[] = {
		D3D_FEATURE_LEVEL_11_1,
		D3D_FEATURE_LEVEL_11_0,
		D3D_FEATURE_LEVEL_10_1,
		D3D_FEATURE_LEVEL_10_0
	};

	UINT creationFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
#ifdef ENABLE_D3D11_CREATE_DEVICE_DEBUG
	creationFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif

	D3D_DRIVER_TYPE driverTypes[] = {
		D3D_DRIVER_TYPE_HARDWARE,
		D3D_DRIVER_TYPE_WARP,
	};

	for (size_t driverTypeIndex = 0; driverTypeIndex < sizeof(driverTypes) / sizeof(driverTypes[0]); ++driverTypeIndex) {
		ComPtr<ID3D11Device> d3d11Device;
		ComPtr<ID3D11DeviceContext> d3d11DeviceContext;

		hResult = ::D3D11CreateDevice(
			nullptr,
			driverTypes[driverTypeIndex],
			nullptr,
			creationFlags,
			featureLevels,
			_countof(featureLevels),
			D3D11_SDK_VERSION,
			&d3d11Device,
			&featureLevelSupported,
			&d3d11DeviceContext);

		if (SUCCEEDED(hResult)) {
			mD3DDevice = d3d11Device;
			mD3DContext = d3d11DeviceContext;
			break;
		}
	}

	DX_CALL_NAMED(hResult, "D3D11CreateDevice");
	DX_CALL(mD3DDevice.As(&mDXGIDevice));

	// 获取DXGI工厂
	ComPtr<IDXGIAdapter> adapter;
	DX_CALL(mDXGIDevice->GetAdapter(&adapter));
	DX_CALL(adapter->GetParent(IID_PPV_ARGS(&mDXGIFactory)));
}

// 实现部分
void Direct3DResource::CleanupResources() {
	// 按照正确的顺序释放资源
	// 先释放依赖其他资源的对象
	mDXGIFactory.Reset();
	mDXGIDevice.Reset();

	// 然后释放D3D上下文和设备
	if (mD3DContext != nullptr) {
		mD3DContext->ClearState();
		mD3DContext->Flush();
	}
	mD3DContext.Reset();
	mD3DDevice.Reset();
}